feat(sounds): W4 五类固定程序化音效与设备级设置 - #45
Conversation
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
918b99a to
90012c7
Compare
603ea8e to
768a895
Compare
重新实现 W4:五类固定程序化音效(action_completed / points_earned / try_again / points_deducted / reward_fulfilled), Web Audio 实时合成、固定配方、每类 2-3 个变体;设备级设置 (总开关、音量、逐事件开关与变体、试听、重置)仅存 localStorage, 不同步云端。接入主流程:加分/扣分/撤销/兑换/兑现;reward_fulfilled 仅在服务端确认“已兑现”后触发。含单元测试与 E2E 测试。
768a895 to
912ae82
Compare
WardLu
left a comment
There was a problem hiding this comment.
QA & Security 复审记录(PR #45,head 912ae82)
结论:COMMENT review。当前认证账号是 PR 作者,GitHub 不允许作者对自己的 PR 提交 REQUEST_CHANGES/approval,因此本条不能计作形式独立 review;但审计发现一个 🟡 中危、发布阻塞的奖励兑现失败状态卡死缺陷。
阻塞项:src/learning-growth-loop-controller.js:347-352 的 reconcileUnconfirmed() 未处理 event.type === "redemption_fulfill"。当服务端对兑现 RPC 返回终态 rejected/conflict(例如并发兑现、奖励已取消或权限/状态冲突)时,outbox 会变为 rejected,但本地 redemption 保持 status: "pending", fulfill_requested: true;UI 因而永久显示“兑现已请求”,没有可重试/恢复路径。独立复现:对精确 head 的 controller 入队兑现后让 transport 返回 rejected/learning_redemption_not_fulfillable,得到该快照与 rejected outbox。
建议:在 reconcileUnconfirmed() 为 redemption_fulfill 增加显式分支;对 retryable 保留可重试语义,对 terminal rejected/conflict 清理或转换 fulfill_requested 并保存 sync_error,让 UI 提供明确重试/失败状态;补充 rejected、retryable、重复确认的 unit test。RPC 仍需继续依赖服务端 household membership/role 校验。
非阻塞项:GitHub CI / CodeQL / Shared Supabase Policy / Vercel checks 均通过;本地精确 head 的新增 unit 30/30、音效 E2E 7/7、check、security:check、build、build-artifact checks 通过。真实设备音量/听感/TTS 互斥仍是 W6 的独立人工验收门禁,浏览器试听件不等同真机证据。
| const debit = next.ledger.find((entry) => entry.redemption_id === redemption.id); | ||
| if (debit && remote?.id) debit.redemption_id = remote.id; | ||
| } | ||
| } else if (event.type === "redemption_fulfill") { |
There was a problem hiding this comment.
Please add the matching failure-state handling for this new redemption_fulfill success branch. reconcileUnconfirmed() below has no branch for this event, so a terminal rejection leaves fulfill_requested: true while the outbox is rejected; the UI cannot recover or retry. Please cover this path with a unit test.
Summary
重新实现 W4:五类固定程序化音效与设备级设置。PR 已 rebase 到
main@eb244cf,当前 head 为912ae82。src/learning-sounds.js:Web Audio 实时合成,固定配方、无随机;五类事件(action_completed/points_earned/try_again/points_deducted/reward_fulfilled),每类 2–3 个变体;同操作优先级、防叠加、连续点击节流、TTS 冲突静音、AudioContext 不可用时静默降级。localStorage,不同步云端。reward_fulfilled仅在服务端确认“已兑现”后经reconcileConfirmed触发。本 PR 不含数据库迁移,不执行生产迁移、
db push或migration repair。Fresh local verification (
912ae82)npm run verify:通过;22 个测试文件、177 项测试通过,build/public/security/build-artifact checks 均通过。npm run test:e2e:73 通过、1 跳过;跳过项为未配置本地真实 Supabase 的cloud-real,PR CI 已在隔离 Supabase 中通过该路径。npm run release:check:通过;生产探测因未设置RELEASE_URL跳过。npm audit --audit-level=high:0 vulnerabilities。origin/main...HEAD)与git diff --check:通过。GitHub checks (
912ae82)verify:通过(首次 E2E 出现两个非 W4 测试的瞬时失败;原 run attempt 2 全量复跑通过)。MERGEABLE/CLEAN,仍保持 Draft。Remaining merge gates
Closes: SHA-6